package handler

import (
	"encoding/json"
	"fmt"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/sirupsen/logrus"
	"io"
	"io/ioutil"
	"math/rand"
	"net/http"
	"regexp"
	"strings"
	"sync"
	"time"
	"wlrIms/config"
	"wlrIms/db"
	"wlrIms/mqttserver"
)

const url = "https://restapi.amap.com/v3/direction/walking"

var cfg config.Cfg
var mqttConfig mqttserver.MQTTConfig
var mqttclient mqtt.Client

const (
	bufferSize = 100 // 设置合适的缓冲区大小
)

func init() {
	logrus.Info("Init Http Server")
	JsonParse := config.NewJsonStruct()
	cfg = JsonParse.LoadCfg()
	mqttConfig.Broker = cfg.MQTT.Broker      //"121.199.58.89"
	mqttConfig.Port = cfg.MQTT.Port          //1883
	mqttConfig.Username = cfg.MQTT.Username  //"admin"
	mqttConfig.Password = cfg.MQTT.Password  //"admin123"
	mqttConfig.PublishTopic = cfg.MQTT.Topic // "communication"
	mqttclient = mqttserver.CreateMQTTClient(mqttConfig)
	go DoWork()
}

// 请求方法
func (pv *GetMapHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var res Resp
	info := Req{}
	//方法不对
	if r.Method != "POST" {
		res.Code = 405
		res.Msg = "url not exist" //代表URL出错了
	}
	body, err := ioutil.ReadAll(r.Body)
	if err != nil && err != io.EOF {
		logrus.Error("处理信息失败 err：", err.Error(), "body:=", string(body))
		res.Code = 400
		res.Msg = "bad request" //代表URL出错了
	} else {
		if err := json.Unmarshal([]byte(string(body)), &info); err != nil {
			res.Code = 406
			res.Msg = "url not exist" //代表URL出错了
		} else {
			//请求相应消息解析
			logrus.Info("The Origin is: ", info.Origin, "The Destination is:", info.Destination)
			data, err := getWalkingPath(info.Origin, info.Destination)
			if err != nil {
				fmt.Println("Error getting walking path:", err)
				res.Code = 404
				res.Msg = "not found resource" //代表URL出错了
			}
			walkingPath, err := parseWalkingPath(data)
			if err != nil {
				fmt.Println("Error parsing walking path:", err)
				res.Code = 404
				res.Msg = "parse data failed" //解析错误
			}

			jsonData, err := json.Marshal(walkingPath)
			if err != nil {
				fmt.Println("Error marshaling JSON:", err)
				res.Code = 404
				res.Msg = "json data failed" //解析错误
			} else {
				res.Code = 200
				res.Msg = string(jsonData)
			}
		}
	}
	logrus.Info("msg:", res.Msg)
	w.Header().Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(res); err != nil {
		logrus.Fatal(err)
		return
	}
}
func (pv *TalkHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var res Result
	var mu sync.Mutex
	info := ReqTalkBody{}
	// 请求相应消息解析
	currentTime := time.Now()
	formattedTime := currentTime.Format("2006-01-02 15:04:05.000")
	defer r.Body.Close()
	// 方法不对
	if r.Method != http.MethodPost {
		res.Status = 405
		res.Response = getRandomString() // 代表URL出错了
		res.Time = string(formattedTime)
	} else {
		body, err := ioutil.ReadAll(r.Body)
		ip := strings.Split(r.RemoteAddr, ":")[0]
		if err != nil && err != io.EOF {
			logrus.Error("处理信息失败 err：", err.Error(), "body:=", string(body))
			res.Status = 400
			res.Response = getRandomString() // 代表URL出错了
			res.Time = string(formattedTime)
		} else {
			if err := json.Unmarshal([]byte(string(body)), &info); err != nil {
				res.Status = 406
				res.Response = getRandomString() // 代表URL出错了
				res.Time = string(formattedTime)
			} else {
				var message MqttMsg
				message.Conn = ip
				message.Prompt = info.Prompt
				jsonBody, err := json.Marshal(message)
				if err != nil {
					res.Status = 406
					res.Response = getRandomString() // 代表URL出错了
					res.Time = string(formattedTime)
				} else {
					logrus.Info("===========msg ", string(jsonBody))
					//查询数据接口
					sqlStr := "SELECT * FROM " + cfg.DataBase.Tblname + " WHERE conn= '" + ip + "'  ORDER BY id DESC LIMIT 5 "
					logrus.Info("sqlStr :", sqlStr)
					//调用QueryData函数
					var bodyStr string
					jsonStr, ok := db.QueryData(ip, message.Prompt, sqlStr)
					if ok {
						jsonBytes, err := json.Marshal(jsonStr)
						if err != nil {
							logrus.Fatal(err)
						}
						bodyStr = string(jsonBytes)
						logrus.Info(" jsonBytes: ", string(jsonBytes))
					}
					mqttserver.PublishMessage(mqttclient, mqttConfig.PublishTopic, bodyStr)
					messageChan := make(chan mqtt.Message)
					go mqttserver.PerformSubscription(mqttclient, ip, messageChan)
					defer mqttserver.CancelSubscription(mqttclient, ip, messageChan)
					var result Result
					select {
					case msg, ok := <-messageChan:
						if !ok {
							res.Status = 500
							res.Response = getRandomString()
							res.Time = formattedTime
							break
						}
						infos := mqttserver.ProcessMessage(mqttclient, msg)
						err := json.Unmarshal([]byte(infos), &result)
						if err != nil {
							fmt.Println("JSON decoding error:", err)
							res.Status = 500
							res.Response = getRandomString()
							res.Time = formattedTime
							break
						} else {
							// 使用正则表达式匹配并替换字符串
							filteredStr := strings.Replace(result.Response, "<|start_header_id|>Assistant<|end_header_id|>", "", -1)
							filteredStr = strings.ReplaceAll(filteredStr, "\n", "")
							filteredStr = strings.ReplaceAll(filteredStr, "\r", "")
							filteredStr = strings.ReplaceAll(filteredStr, "[user]", "")
							filteredStr = strings.ReplaceAll(filteredStr, "[system]", "")
							regex := regexp.MustCompile(`\s+`)
							filteredStr = regex.ReplaceAllString(filteredStr, " ")
							res.Response = filteredStr
							res.Status = result.Status
							res.Time = result.Time

							//插入数据库中的数据
							var msgs []db.JsonData
							msgInfo := db.JsonData{
								Conn: ip,
								Ask:  info.Prompt,
								Ans:  res.Response,
							}
							msgs = append(msgs, msgInfo)
							//插入数据库
							sql := " insert into " + cfg.DataBase.Tblname + " (conn, ask, ans) values(?,?,?)"
							isOk := db.InsertDataBatches(sql, msgs)
							logrus.Info("Insert data is isOk ", isOk)
						}
					case <-time.After(5 * time.Second): // 设置超时时间为5秒
						res.Status = 408
						res.Response = getRandomString() // 超时错误信息
						res.Time = string(formattedTime)
					}
				}

			}
		}
	}

	w.Header().Set("Content-Type", "application/json")
	mu.Lock()
	defer mu.Unlock()
	if err := json.NewEncoder(w).Encode(res); err != nil {
		logrus.Fatal(err)
		return
	}
}

func getWalkingPath(origin, destination string) (map[string]interface{}, error) {
	queryParams := map[string]string{
		"key":         cfg.APIKey,
		"origin":      origin,
		"destination": destination,
		"extensions":  "all",
	}

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}

	q := req.URL.Query()
	for key, value := range queryParams {
		q.Add(key, value)
	}
	req.URL.RawQuery = q.Encode()

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var data map[string]interface{}
	err = json.Unmarshal(body, &data)
	if err != nil {
		return nil, err
	}

	return data, nil
}

func parseWalkingPath(data map[string]interface{}) (*WalkingPath, error) {
	if status, ok := data["status"].(string); ok && status == "1" {

		route, ok := data["route"].(map[string]interface{})
		if !ok {
			return nil, fmt.Errorf("未找到导航路线")
		}

		paths, ok := route["paths"].([]interface{})
		if !ok || len(paths) == 0 {
			return nil, fmt.Errorf("未找到导航路径")
		}
		steps, ok := paths[0].(map[string]interface{})["steps"].([]interface{})
		if !ok {
			return nil, fmt.Errorf("未找到导航步骤")
		}

		walkingPath := &WalkingPath{
			Instructions: make([]Instruction, 0),
		}

		for _, step := range steps {
			instruction := step.(map[string]interface{})["instruction"].(string)
			polyline := step.(map[string]interface{})["polyline"].(string)

			points := strings.Split(polyline, ";")
			coordinates := make([]Coordinate, 0)

			for _, point := range points {
				coords := strings.Split(point, ",")
				latitude := coords[1]
				longitude := coords[0]
				coordinate := Coordinate{
					Latitude:  latitude,
					Longitude: longitude,
				}
				coordinates = append(coordinates, coordinate)
			}

			walkingPath.Instructions = append(walkingPath.Instructions, Instruction{
				Text:        instruction,
				Polyline:    polyline,
				Coordinates: coordinates,
			})
		}
		return walkingPath, nil
	} else {
		return nil, fmt.Errorf("导航请求失败: %s", data["info"])
	}
}

func DoWork() {
	// 创建定时器，每隔一秒钟检测一次磁盘容量
	//读取key值
	JsonParse := config.NewJsonStruct()
	cfg = JsonParse.LoadCfg() //获取结构体信息
	logrus.Info("APIKey: ", cfg.APIKey)
	ticker := time.NewTicker(30 * time.Minute)
	for {
		select {
		case <-ticker.C:
			// 获取磁盘状态信息
			//读取key值
			JsonParse := config.NewJsonStruct()
			cfg = JsonParse.LoadCfg() //获取结构体信息
			//设置定时获取
			logrus.Info("APIKey: ", cfg.APIKey)
		}
	}
}

/*
********************************************
1.brief: 温情提示语
2.function:请求错误提示语
********************************************
*/
func getRandomString() string {
	strings := []string{
		"您的问题难倒了还在成长的小西，我后面一定努力学习，争取回答您所有问题。",
		"小西的CPU快烧着了，让我在努力的想一想。",
		"您的问题真有水平，我都回答不上来了，我要赶紧去学习了。",
		"小西有点困，我想休息了，祝您生活愉快。",
		"您的问题有点难，回头我翻翻书，希望可以帮您找到答案。",
	}
	rand.Seed(time.Now().UnixNano())
	randomIndex := rand.Intn(len(strings))
	return strings[randomIndex]
}
